/*
 * @author: skinoll
 * @description: layui搜索bar组件
 * @version 1.0.1
 * @License：MIT
 */
layui.define(['form', 'laydate'], function (exports) {
  var form = layui.form,
    laydate = layui.laydate,
    LINKAGE_FIRST_CLASS = 'rs-linkage-first',
    submitCount = 0,
    timeRangeCount = 0,
    selectCount = 0

  // 渲染搜索栏
  function Render($container, columns) {
    this.asyncSelectCache = []
    this.$container = $container
    this.columns = columns

    var _this = this,
      html = ['<form class="layui-form layui-form-pane" action=""><div class="layui-form-item">'],
      timeRangeParam = []
    for (var i = 0, len = columns.length; i < len; i++) {
      var c = columns[i]
      // 时间范围选择
      if (c.type === 'timeRange') {
        c.cols[0].id = 'rs-timerange-f' + timeRangeCount++
        c.cols[1].id = 'rs-timerange-f' + timeRangeCount++
        timeRangeParam.push(c)
      }
      html.push(this[c.type](c, $container))
    }
    html.push('</div></form>')
    $container.html(html.join(''))

    timeRangeParam.length && this.doRenderTimeRange(timeRangeParam)
    form.render()

    setTimeout(function () {
      _this.doCss($container)
    }, 0)

    // 渲染延迟加载的select
    this.doRenderAyncSeclect($container)
  }

  // 包装行内表单
  Render.prototype.wrapInline = function (inner, label, width, labelStyle) {
    var inline = ['<div class="layui-inline">']
    if (label) {
      var style = 'style="width:auto;'
      if (labelStyle) {
        style += labelStyle
      }
      style += '"'
      inline.push('<label class="layui-form-label" ' + style + '>' + label + '</label>')
    }
    inline.push('<div class="layui-input-inline" style="width: ' + width + 'px;">')
    inline.push(inner)
    inline.push('</div></div>')
    return inline.join('')
  }

  /**
   * 渲染下拉
   * @param param.name => 【必填】 select的name属性
   * @param param.selectOpts[] => 【必填】 selected：true为选中,可以忽略，value:value值，content：文字，linkageOpts[]：同selectOpts，当前选项触发的切换关联select的内容
   * @param param.linkage => 【可选】配置此选项，关联一个select紧跟在此select后面，必须配置selectOpts里的linkageOpts，
   *                               linkage.name：关联的select的name（所有的opts的name必须设置为一个，可以只设置第一个）,其他的选项除了selectOpts均可设置
   * @param param.linkInput => 【可选】 配置此选项，配置一个input紧跟select标题。选项为input的所有选项
   * @param param.label => 【可选】 false不使用label，为字符串时为select的label
   * @param param.labelStyle 【可选】 labelStyle label的样式
   * @param param.laySearch 【可选】 是否开启搜索，默认false
   * @param param.width => 【可选】 select的宽度，默认160
   * @param param.onselect 【可选】 选择时触发回调，携带三个参数value（选择的值），othis（美化后的DOM对象），elem（原始DOM对象）
   * @param param.async {Object} 【可选】 异步获取选项，使用此参数时，url和parseResponse参数必填
   *                               async.url 请求选项的地址
   *                               async.param 请求的参数
   *                               async.default 默认的选项，默认{value:'',content:'全部'}
   *                               async.parseResponse 函数，处理返回的接口，参数为请求url的返回值，函数返回值[{value: 'option的value', content:'option显示的内容'}..]
   */
  Render.prototype.select = function (param, $container) {
    var _this = this,
      getSelect = function (_param, linkSelectName, linkInputName) {
        var selectOpts = _param.selectOpts
        var layfilter = 'rs-select-f' + selectCount++
        var selectClass = !!linkSelectName || !!linkInputName ? ' class="' + LINKAGE_FIRST_CLASS + '"' : ''
        var laySearchAttr = !!_param.laySearch ? ' lay-search' : ''
        var selectHtml = [
          '<select name=' + _param.name + ' lay-filter=' + layfilter + selectClass + laySearchAttr + '>'
        ]
        // key：父select的option的value，value：关联的linkageOpts
        var linkSelectMap = {}
        // 判断是否有异步参数，如果有则使用异步参数
        // FIXME 异步多select联动
        if (param.async) {
          selectOpts = [param.async.default || (param.async.default = { value: '', content: '全部' })]
        }
        for (var i = 0, len = selectOpts.length; i < len; i++) {
          var opt = selectOpts[i]
          linkSelectMap[opt.value] = opt.linkageOpts
          var backQute = opt.selected ? ' selected="selected">' : '>'
          selectHtml.push('<option value=' + opt.value + backQute + opt.content + '</option>')
        }
        selectHtml.push('</select>')
        // 绑定选择事件
        if (_param.onselect || linkSelectName) {
          form.on('select(' + layfilter + ')', function (data) {
            if (linkSelectName) {
              var copts = linkSelectMap[data.value],
                chtml = ''
              for (var j = 0, clen = copts.length; j < clen; j++) {
                var nowOpt = copts[j]
                chtml += '<option value=' + nowOpt.value + '>' + nowOpt.content + '</option>'
              }
              $container.find('select[name="' + linkSelectName + '"]').html(chtml)
              form.render()
            }
            _param.onselect && _param.onselect(data.value, data.othis, data.elem)
          })
        }
        return _this.wrapInline(selectHtml.join(''), _param.label, _param.width || 160, _param.labelStyle)
      }

    var linkSelectName = param.linkage && param.linkage.name
    var linkInputName = param.linkInput && param.linkInput.name
    var res = getSelect(param, linkSelectName, linkInputName)
    if (param.linkage) {
      // 判断选中的那一个，关系到下一个联动的options
      var selectOption = '',
        selectOpts = param.selectOpts
      for (var i = 0, len = selectOpts.length; i < len; i++) {
        var opt = selectOpts[i]
        if (opt.selected) {
          selectOption = opt
        }
      }
      if (!selectOption) {
        selectOption = selectOpts[0]
      }
      param.linkage.selectOpts = selectOption.linkageOpts
      res += getSelect(param.linkage)
    } else if (param.linkInput) {
      res += this.input(param.linkInput)
    }

    // 处理异步参数
    // FIXME 现在暂时只支持单select，不支持联动
    if (param.async) {
      this.asyncSelectCache.push({
        async: param.async,
        selectName: param.name
      })
    }
    return res
  }

  /**
   * 渲染input
   * @param param.name 【必填】 name
   * @param param.default【可选】 默认值
   * @param param.label 【可选】 label
   * @param param.labelStyle 【可选】 labelStyle label的样式
   * @param param.placeholder【可选】
   * @param param.width 【可选】 宽度，默认160
   */
  Render.prototype.input = function (param) {
    var inner =
      '<input type="text" name=' +
      param.name +
      ' placeholder="' +
      (param.placeholder || '') +
      '"' +
      ' value="' +
      (param.default || '') +
      '" autocomplete="off" class="layui-input">'
    return this.wrapInline(inner, param.label, param.width || 160, param.labelStyle)
  }

  /**
   * 渲染按钮
   * @param param.content 【必填】 按钮内容
   * @param param.class 【可选】 class，默认layui-btn
   * @param param.style 【可选】 style字符串
   * @param param.width 【可选】 宽度，默认100
   * @param param.onclick 【可选】 点击时触发回调，携带三个参数field, elem, form
   */
  Render.prototype.button = function (param) {
    var inner = ''
    var clazz = 'class="' + (param.class || 'layui-btn') + '"'
    if (param.style) {
      clazz += ' style="' + param.style + '"'
    }
    var layfilter = 'rs-submit-btn-f' + submitCount++
    inner =
      '<button type="button" ' + clazz + ' lay-submit lay-filter=' + layfilter + '>' + param.content + '</button >'
    if (param.onclick) {
      form.on('submit(' + layfilter + ')', function (data) {
        param.onclick(data.field, data.elem, data.form)
        return false //阻止表单跳转。如果需要表单跳转，去掉这段即可。
      })
    }
    return this.wrapInline(inner, null, param.width || 100)
  }

  /**
   * 渲染时间选框（开始，结束）
   * @param param.cols[] 【必填】 配置每个时间选框的属性 => 【必填】name：input的name属性，【可选】type：laydate组件的type，默认
   *                       datetime，【可选】default：默认值，【可选】placeholder：提示
   * @param param.label 【可选】 label
   * @param param.labelStyle 【可选】 labelStyle label的样式
   * @param param.width 【可选】宽度，默认160
   */
  Render.prototype.timeRange = function (param) {
    var _cols0 = param.cols[0],
      _cols1 = param.cols[1],
      width = param.width || 160,
      id0 = ' id="' + _cols0.id + '"',
      name0 = ' name="' + _cols0.name + '"',
      placeholder0 = ' placeholder="' + (_cols0.placeholder || '开始时间') + '"',
      default0 = ' value="' + (_cols0.default || '') + '"',
      id1 = ' id="' + _cols1.id + '"',
      name1 = ' name="' + _cols1.name + '"',
      placeholder1 = ' placeholder="' + (_cols1.placeholder || '结束时间') + '"',
      default1 = ' value="' + (_cols1.default || '') + '"'
    var inline = [
      '<div class="layui-input-inline" style="width: ' +
        width +
        'px;"><input type="text" class="layui-input" ' +
        id0 +
        name0 +
        placeholder0 +
        default0 +
        '></div>',
      '<div class="layui-form-mid">-</div>',
      '<div class="layui-input-inline" style="width: ' +
        width +
        'px;"><input type="text" class="layui-input" ' +
        id1 +
        name1 +
        placeholder1 +
        default1 +
        '></div>'
    ]
    if (param.label) {
      var style = 'style="width:auto;'
      if (param.labelStyle) {
        style += param.labelStyle
      }
      style += '"'
      inline.unshift('<label class="layui-form-label" ' + style + '>' + param.label + '</label>')
    }
    inline.unshift('<div class="layui-inline">')
    inline.push('</div>')
    return inline.join('')
  }

  /**
   * 处理css
   */
  Render.prototype.doCss = function ($container) {
    // $container.css({ padding: '15px 10px 0 10px' })
    $container.find('.layui-form-item').css({ margin: 0 })
    // 所有inline的margin置为0
    $container.find('.layui-inline').css({ 'margin-right': 0 })
    // 处理联动select
    $container
      .find('.' + LINKAGE_FIRST_CLASS)
      .parent()
      .css({ 'margin-right': 0 })
      .find('.layui-select-title input')
      .css({ 'background-color': '#FBFBFB' })
    $container.find('.layui-form-mid').css({ 'margin-right': 5 }).prev('.layui-input-inline').css({ 'margin-right': 5 })
  }

  /**
   * 渲染时间选择框
   */
  Render.prototype.doRenderTimeRange = function (param) {
    for (var j = 0, len = param.length; j < len; j++) {
      var single = param[j],
        cols = single.cols
      for (var i = 0, clen = cols.length; i < clen; i++) {
        var singleCol = cols[i]
        laydate.render({
          elem: '#' + singleCol.id,
          type: singleCol.type || 'datetime'
        })
      }
    }
  }

  /**
   * 渲染异步的select
   */
  Render.prototype.doRenderAyncSeclect = function ($container) {
    while (this.asyncSelectCache.length > 0) {
      var p = this.asyncSelectCache.pop()
      !(function (p) {
        var async = p.async
        $.post(async.url, async.param, function (res) {
          var optHtml = '',
            opts = async.parseResponse(res) || []
          opts.unshift(async.default)
          for (var i = 0, len = opts.length; i < len; i++) {
            var nowOpt = opts[i]
            optHtml += '<option value=' + nowOpt.value + '>' + nowOpt.content + '</option>'
          }
          $container.find('select[name="' + p.selectName + '"]').html(optHtml)
          form.render()
        })
      })(p)
    }
  }

  exports('laySearchBar', function ($container, columns) {
    return new Render($container, columns)
  })
})
